#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
代码扫描器(JavaScanner)：用于扫描代码库目录结构

主要功能：
1. 扫描所有Java文件路径
2. 根据文件名创建基本类信息填充class_list
"""

import os
import logging
from typing import Dict, List, Set, Optional, Tuple
import re

# 导入数据结构
from parser.refactor.data_structures import ClassInfo, ClassType, Visibility, PackageInfo

logger = logging.getLogger(__name__)

class JavaScanner:
    """目录扫描器，用于扫描项目目录结构并提取基本信息"""
    
    def __init__(self, repo_path: str):
        """
        初始化目录扫描器
        
        Args:
            repo_path: 代码仓库路径
        """
        # 姜郑恒：初始化必要的变量
        self.repo_path = repo_path
        self.file_extension = '.java'  # Java文件扩展名
        
        # 包信息列表
        self.package_list: List[PackageInfo] = []
    
    def scan_directory(self) -> Tuple[List[ClassInfo], List[PackageInfo]]:
        """
        扫描目录，获取所有Java文件并创建基本类信息
        
        Returns:
            class_list: 类信息列表
            package_list: 包信息列表
        """
        # 姜郑恒：实现简化版扫描逻辑，只创建基本类信息
        logger.info(f"开始扫描目录: {self.repo_path}")
        
        class_list: List[ClassInfo] = []
        package_names = set()  # 用于跟踪已处理的包名
        
        # 遍历目录中的所有文件
        for root, _, files in os.walk(self.repo_path):
            for file in files:
                if file.endswith(self.file_extension):
                    file_path = os.path.join(root, file)
                    try:
                        # 从文件名推断类名 (去掉扩展名)
                        class_name = os.path.splitext(file)[0]
                        
                        # 尝试从文件快速提取包名 (仅读取前几行查找package声明)
                        package_name = self._quick_extract_package(file_path)
                        
                        # 创建类信息对象
                        class_info = self._create_class_info(class_name, package_name, file_path)
                        class_list.append(class_info)
                        
                        # 添加到包信息列表（避免重复）
                        if package_name and package_name not in package_names:
                            relative_path = self._get_relative_path(file_path, self.repo_path)
                            path_to_use = relative_path if relative_path else file_path
                            
                            package_info = PackageInfo(
                                name=package_name,
                                relative_path=path_to_use
                            )
                            self.package_list.append(package_info)
                            package_names.add(package_name)
                    except Exception as e:
                        logger.error(f"处理文件时出错: {str(e)}")

        print(self.package_list)
        logger.info(f"扫描完成，发现 {len(class_list)} 个类，{len(self.package_list)} 个包")
        return class_list, self.package_list
    
    def _quick_extract_package(self, file_path: str) -> str:
        """
        快速提取文件中的包名 (只读取前几行)
        
        Args:
            file_path: 文件路径
            
        Returns:
            包名或空字符串
        """
        # 姜郑恒：实现快速提取包名
        try:
            package_pattern = re.compile(r'package\s+([\w.]+)\s*;')
            with open(file_path, 'r', encoding='utf-8') as f:
                # 只读取前10行查找包名
                for _ in range(10):
                    line = f.readline()
                    if not line:
                        break
                    
                    # 查找包名
                    match = package_pattern.search(line)
                    if match:
                        return match.group(1)
            
            return ""
        except Exception as e:
            logger.warning(f"提取包名时出错: {str(e)}")
            return ""
    
    def _create_class_info(self, class_name: str, package_name: str, file_path: str) -> ClassInfo:
        """
        创建类信息对象
        
        Args:
            class_name: 类名
            package_name: 包名
            file_path: 文件路径
            
        Returns:
            类信息对象
        """
        # 构建全限定类名
        full_name = class_name
        if package_name:
            full_name = f"{package_name}.{class_name}"
        
        # 创建并返回ClassInfo对象
        return ClassInfo(
            name=class_name,
            full_name=full_name,
            package=package_name,
            file_path=file_path,
            type=ClassType.CLASS,
            visibility=Visibility.PUBLIC,
            is_parsed=False
        )

    def _get_relative_path(self, file_path, repo_path):
        """
        获取文件相对于仓库的相对路径

        参数:
            file_path (str): 文件的绝对路径
            repo_path (str): 仓库的绝对路径

        返回:
            str: 文件相对于仓库的相对路径
        """
        # 标准化路径
        file_path = os.path.normpath(file_path)
        repo_path = os.path.normpath(repo_path)

        # 获取文件所在目录的绝对路径
        file_dir = os.path.dirname(file_path)

        # 计算相对于仓库的路径
        relative_dir = os.path.relpath(file_dir, start=repo_path)

        return relative_dir